home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 October: Windmill on DISC / ADC Developer CD (1993-10) (''Windmill On DISC'')_iso / Dev.CD Oct 93.iso / System Software / U.S. System Software / System 7 Pro™ Beta 11 / Development Tools / Sample Code / Standard Mail / CollaboDraw (w⁄DigiSign) / myaoce.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-11  |  18.9 KB  |  911 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------------------------
  2.  *
  3.  * Simple Sample AOCE Application Framework
  4.  *
  5.  * ©1991-1993 Apple Computer
  6.  *
  7.  -------------------------------------------------------------------------------------*/
  8. /*
  9.  * myaoce.c -- aoce-specific routines
  10.  *
  11.  * change history:
  12.  *
  13.  * SJF        04/21/93        1.0b2        update to b2
  14.  * SJF        03/01/93        1.0b1        added digital signatures
  15.  * SJF        02/09/93        1.0b1        update to b1
  16.  * SJF        10/13/92        1.0d4        update to a11
  17.  * SJF        09/09/92        1.0d3        update to a9
  18.  * SJF        05/07/92        1.0d2        update to a6
  19.  * SJF        11/06/91        1.0d1        initial coding
  20.  *
  21.  */
  22.  
  23. #define    kGestaltTrap    0xA0AD 
  24.  
  25. #ifndef __SCRIPT__
  26. #include <Script.h>
  27. #endif
  28.  
  29. #ifndef __FILES__
  30. #include <Files.h>
  31. #endif
  32.  
  33. #ifndef __FOLDERS__
  34. #include <Folders.h>
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __PACKAGES__
  42. #include <Packages.h>
  43. #endif
  44.  
  45. #ifndef __TRAPS__
  46. #include <Traps.h>
  47. #endif
  48.  
  49. #ifndef __GESTALTEQU__
  50. #include <GestaltEqu.h>
  51. #endif
  52.  
  53. #ifndef __TOOLUTILS__
  54. #include <ToolUtils.h>
  55. #endif
  56.  
  57. #ifndef __OCE__
  58. #include <OCE.h>
  59. #endif
  60.  
  61. #ifndef __OCESTANDARDDIRECTORY__
  62. #include <OCEStandardDirectory.h>
  63. #endif
  64.  
  65. #ifndef __OCESTANDARDMAIL__
  66. #include <OCEStandardMail.h>
  67. #endif
  68.  
  69. #ifndef __OCEAUTHDIR__
  70. #include <OCEAuthDir.h>
  71. #endif
  72.  
  73. #ifndef __OCEERRORS__
  74. #include <OCEErrors.h>
  75. #endif
  76.  
  77. #include <string.h>
  78.  
  79. #include "const.h"
  80. #include "mytypes.h"
  81. #include "globals.h"
  82. #include "windowstuff.h"
  83. #include "draw.window.h"
  84. #include "draw.mailer.window.h"
  85. #include "utils.h"
  86. #include "myevents.h"
  87. #include "trapavailable.h"
  88. #include "windutils.h"
  89. #include "strconst.h"
  90. #include "commands.h"
  91. #include "mymenus.h"
  92. #include "digisig.h"
  93.  
  94. #include "myaoce.h"
  95.  
  96.  
  97. /* static globals */
  98.  
  99. static LocalIdentity gIdentity;
  100.  
  101.  
  102. pascal void DrawImageProc(long refcon, Boolean inColor);
  103.  
  104.  
  105. // HasAOCE
  106. //
  107. // returns true only of AOCE is available and running
  108. //
  109. Boolean HasAOCE(void)
  110. {
  111.     OSErr err;
  112.     long response;
  113.     
  114.     if (!TrapAvailable(kGestaltTrap))
  115.         return false;
  116.     
  117.     err = Gestalt(gestaltOCEToolboxAttr,&response);
  118.     if (err!=noErr)
  119.         return false;
  120.         
  121.     return (response && (response << gestaltOCETBAvailable));
  122. }
  123.  
  124.  
  125. OSErr InitAOCE(void)
  126. {
  127.     OSErr err;
  128.     
  129.     SetCursor(&gWatchCursor);
  130.     err = SMPInitMailer(kSMPVersion);
  131.     SetCursor(&qd.arrow);
  132.  
  133.     if (err!=noErr)
  134.         return err;
  135.  
  136.     return GetLocalIdentity();
  137. }
  138.  
  139.  
  140. void CommAddRemoveMailer(WindowPtr window)
  141. {    
  142.     SetCursor(&gWatchCursor);    // this may take some time
  143.  
  144.     if (IsWindowType(window,kDrawWindow))    // we add mailers to drawing windows
  145.         CommAddMailer(window);
  146.     else if (IsWindowType(window,kDrawMailerWindow))
  147.         CommRemoveMailer(window);
  148.     
  149.     SetCursor(&qd.arrow);        // done waiting
  150. }
  151.  
  152.  
  153. void CommAddMailer(WindowPtr window)
  154. {
  155.     Boolean chFlag = false;
  156.     GrafPtr savePort;
  157.     Rect rectToInval;
  158.     
  159.     SendWindowMessage(window,kDeactivateMessage,&chFlag);
  160.  
  161.     GetPort(&savePort);
  162.     SetPort(window);
  163.     rectToInval = window->portRect;
  164.     rectToInval.bottom -= kScrollBarWidth;
  165.     rectToInval.right -= kScrollBarWidth;
  166.     EraseRect(&rectToInval);
  167.     InvalRect(&rectToInval);
  168.     SetPort(savePort);
  169.  
  170.     MakeMailerFromDrawing(window);
  171.     SendWindowMessage(window,kActivateMessage,&chFlag);
  172. }
  173.  
  174.  
  175.  
  176. void CommRemoveMailer(WindowPtr window)
  177. {
  178.     Boolean chFlag = false;
  179.     GrafPtr savePort;
  180.     Rect rectToInval;
  181.     
  182.     SendWindowMessage(window,kDeactivateMessage,&chFlag);
  183.  
  184.     GetPort(&savePort);
  185.     SetPort(window);
  186.     rectToInval = window->portRect;
  187.     rectToInval.bottom -= kScrollBarWidth;
  188.     rectToInval.right -= kScrollBarWidth;
  189.     EraseRect(&rectToInval);
  190.     InvalRect(&rectToInval);
  191.     SetPort(savePort);
  192.  
  193.     MakeDrawingFromMailer(window);
  194.     SendWindowMessage(window,kActivateMessage,&chFlag);
  195. }
  196.  
  197.  
  198. void CommSendLetter(WindowPtr window)
  199. {
  200.     char hState;
  201.     WInfoPtr infoPtr;
  202.     OSErr err;
  203.     Boolean mustAddContent;
  204.     Str255 docTitle;
  205.     Str255 nativeFormat;
  206.     StringPtr nativeFormatArray[1];
  207.  
  208.     GetResString(nativeFormat,kAppNameID,kAppName);
  209.  
  210.     infoPtr = BeginWindowAccess(window,&hState);
  211.     
  212.     GetWTitle(window,docTitle);
  213.     nativeFormatArray[0] = (StringPtr)nativeFormat;
  214.     SetCursor(&qd.arrow);
  215.     err = SMPSendOptionsDialog(window,docTitle,nativeFormatArray,1,
  216.             kSMPNativeMask|kSMPImageMask|kSMPStandardInterchangeMask,&gPreferences.sendFormat,nil,0L,
  217.             &gPreferences.sendFormat,&gPreferences.sendOptions);
  218.     
  219.     if (err==-128)
  220.         return;
  221.         
  222.     if (err!=noErr) {
  223.         DoError(err);
  224.         return;
  225.     }
  226.         
  227.     SetCursor(&gWatchCursor);    // this may take some time
  228.  
  229.     err = SMPBeginSend(window,kAppCreator,kCDLtrMsgType,&gPreferences.sendOptions,&mustAddContent);
  230.     if (err!=noErr) {
  231.         SetCursor(&qd.arrow);        // done waiting
  232.         EndWindowAccess(window,hState);
  233.         DoError(err);
  234.         return;
  235.     }
  236.  
  237.     if (mustAddContent) {
  238.         if (err==noErr)
  239.             err = AddLetterBlocks(window,infoPtr,&gPreferences.sendFormat);
  240.         if (err!=noErr)
  241.             DoError(err);
  242.     }
  243.             
  244.     err = SMPEndSend(window,(err==noErr));
  245.     if (err!=noErr)
  246.         DoError(err);
  247.     
  248.     EndWindowAccess(window,hState);
  249.  
  250.     if ((err==noErr) && gPreferences.closeOnSend)
  251.         CommCloseWindow(window);
  252.         
  253.     SetCursor(&qd.arrow);        // done waiting
  254. }
  255.  
  256.  
  257. OSErr LoSaveLetter(WindowPtr window,WInfoPtr infoPtr,SMPSaveType saveType)
  258. {
  259.     OSErr err,err2;
  260.     FSSpec *fSpec;
  261.     Boolean mustAddContent;
  262.     
  263.     err = err2 = noErr;
  264.     
  265.     SetCursor(&gWatchCursor);    // this may take some time
  266.  
  267.     fSpec = &infoPtr->fileSpec;
  268.     err = SMPBeginSave(window,fSpec,kAppCreator,kCDLtrMsgType,saveType,&mustAddContent);
  269.     if (err!=noErr) {
  270.         SetCursor(&qd.arrow);        // done waiting
  271.         return err;
  272.     }
  273.  
  274.     if (mustAddContent) {
  275.         if (err==noErr)
  276.             err2 = AddLetterBlocks(window,infoPtr,nil);
  277.         else
  278.             err2 = noErr;
  279.     }
  280.     
  281.     err = SMPEndSave(window,(err==noErr));
  282.     if (err!=noErr)
  283.         return err;
  284.  
  285.     if (err==noErr) {
  286.         infoPtr->otherData[kLastChangedData] = 0;
  287.     }
  288.     
  289.     SetCursor(&qd.arrow);        // done waiting
  290.     
  291.     if (err==noErr)
  292.         return err2;
  293.     else
  294.         return err;
  295. }
  296.  
  297.  
  298. void CommReply(WindowPtr window,Boolean replyToAll)
  299. {
  300.     WindowPtr replyWindow;
  301.     Point topLeft = {0,0};
  302.     Str255 newTitle;
  303.     Rect newWindRect;
  304.     Point *ptPtr;
  305.     OSErr err;
  306.     
  307.     GetResString(newTitle,kDefaultFilenameID,kDefaultFilename);
  308.     newWindRect = window->portRect;
  309.     SetPort(window);
  310.     ptPtr = (Point *)&newWindRect;
  311.     LocalToGlobal(ptPtr++);
  312.     LocalToGlobal(ptPtr);
  313.     OffsetRect(&newWindRect,kWindowOffset,kWindowOffset);
  314.     
  315.     replyWindow = MakeWindow(kDrawMailerWindow,&newWindRect,newTitle,false);
  316.     err = SMPMailerReply(window,replyWindow,replyToAll,topLeft,true,true,gIdentity,nil,0L);
  317.     if (err!=noErr)
  318.         DoError(err);
  319.     ShowWindow(replyWindow);
  320. }
  321.  
  322.  
  323. void CommForward(WindowPtr window)
  324. {
  325.     WInfoPtr infoPtr;
  326.     char hState;
  327.     
  328.     OSErr err;
  329.     
  330.     infoPtr = BeginWindowAccess(window,&hState);
  331.  
  332.     HandleExpand(window,infoPtr);    // expand the window before doing the forward
  333.         
  334.     err = SMPMailerForward(window,gIdentity);
  335.     if (err!=noErr)
  336.         DoError(err);
  337.     
  338.     infoPtr->saved = false;
  339.     
  340.     DMailerActivateWindow(window,infoPtr,nil);
  341.     EndWindowAccess(window,hState);
  342. }
  343.  
  344.  
  345. void CommAdjacentLetter(void)
  346. {
  347.     OSErr err;
  348.     LetterDescriptor newLetter,**oldLetter;
  349.     OSType ltrType;
  350.     WindowPtr window;
  351.     WInfoPtr infoPtr;
  352.     char hState,hState2;
  353.     
  354.     SetCursor(&gWatchCursor);
  355.  
  356.     ltrType = kCDLtrMsgType;
  357.     err = SMPGetNextLetter(<rType,1,&newLetter);
  358.     
  359.     for (window=FrontWindow(); window!=nil; window=(WindowPtr)((WindowPeek)window)->nextWindow) {
  360.         infoPtr = BeginWindowAccess(window,&hState);
  361.         if (IsWindowType(window,kDrawMailerWindow)) {
  362.             oldLetter = (LetterDescriptor **)infoPtr->otherData[kLetterDescData];
  363.             hState2 = HGetState((Handle)oldLetter);
  364.             HLock((Handle)oldLetter);
  365.             if (SameLetter(*oldLetter,&newLetter))
  366.                 err = kInternalError;                // don't open letter if it's already open
  367.             HSetState((Handle)oldLetter,hState2);
  368.         }
  369.         EndWindowAccess(window,hState);
  370.     }
  371.     
  372.     if (err==noErr) {
  373.         err = LoOpen(false,nil,&newLetter.u.mailboxSpec,true,&window);
  374.         if (err!=noErr)
  375.             DoError(err);
  376.     }
  377.     else
  378.         SysBeep(1);        // no adjacent letters
  379.  
  380.     SetCursor(&qd.arrow);        
  381. }
  382.  
  383.  
  384. void CommTagLetter(void)
  385. {
  386.     RString32 tag;
  387.     OSErr err;
  388.     
  389.     tag.dataLength = 0;
  390.     err = SMPTagDialog(FrontWindow(),&tag);
  391.     if (err!=noErr)
  392.         DoError(err);
  393. }
  394.  
  395.  
  396. OSErr GetLocalIdentity(void)
  397. {
  398.     OSErr err;
  399.     SDPIdentityKind idKind;
  400.     AuthGetLocalIdentityPB pBlock;
  401.     Str255 authString;
  402.     
  403.     GetResString(authString,kAuthStringID,kAuthString);
  404.     
  405.     err = AuthGetLocalIdentity((AuthParamBlockPtr)&pBlock,false);
  406.  
  407.     if (err!=noErr)
  408.         err = SDPPromptForID(&gIdentity,nil,nil,authString,nil,kSDPLocalIdentityMask,&idKind,nil,0);
  409.     else
  410.         gIdentity = pBlock.theLocalIdentity;
  411.         
  412.     return err;
  413. }
  414.  
  415.  
  416. OSErr ProcessAOCEEvent(WindowPtr window,WInfoPtr infoPtr,const EventRecord *ev,SMPMailerResult *mailResult)
  417. {
  418.     #pragma unused (window,infoPtr)
  419.     
  420.     return SMPMailerEvent(ev,mailResult,nil,0L);
  421. }
  422.  
  423.  
  424. Boolean ProcessAOCEWhatHappened(WindowPtr window,WInfoPtr infoPtr,SMPMailerResult mailResult)
  425. {
  426.     OSErr err;
  427.     SMPMailerState state;
  428.     long *lastChanged;
  429.     
  430.     // see if the mailer has changed
  431.         
  432.     err = SMPGetMailerState(window, &state);
  433.     if (err != noErr)
  434.         DoError(err);
  435.  
  436.     lastChanged = (long *) &infoPtr->otherData[kLastChangedData];
  437.     if (*lastChanged!=state.changeCount) {
  438.         *lastChanged = state.changeCount;
  439.         infoPtr->changed = true;
  440.         FixMailerMenus(window,infoPtr);
  441.     }
  442.  
  443.     if (mailResult & kSMPContractedMask)
  444.         HandleContract(window,infoPtr);
  445.  
  446.     if (mailResult & kSMPExpandedMask)
  447.         HandleExpand(window,infoPtr);
  448.  
  449.     if ((mailResult & kSMPMailerBecomesTargetMask) ||
  450.         (mailResult & kSMPAppBecomesTargetMask))
  451.             FixMailerMenus(window,infoPtr);
  452.     
  453.     // actually, we want to check the menus for *every* event that the mailer handles completely, since we may
  454.     // need to change the Undo item in the File menu to keep it up to date
  455.     
  456.     if (mailResult & kSMPAppShouldIgnoreEventMask)
  457.         FixMailerMenus(window,infoPtr);
  458.         
  459.     if (mailResult & kSMPAppMustHandleEventMask)
  460.         return false;    // app must handle this event
  461.     else return true;    // mailer handled this event completely
  462. }
  463.  
  464.  
  465. void MakeMailerFromDrawing(WindowPtr window)
  466. {
  467.     WInfoPtr infoPtr;
  468.     char hState;
  469.     Point topLeft = {0,0};
  470.     OSErr err;
  471.     short mWidth,contHeight,expHeight;
  472.     
  473.     SetWindowKind(window,kDrawMailerWindow);
  474.  
  475.     infoPtr = BeginWindowAccess(window,&hState);
  476.  
  477.     SetDMailerMethods(infoPtr);
  478.     infoPtr->otherFlags[kMailerExpanded] = gPreferences.expandOnCreate;
  479.     
  480.     if (infoPtr->fRefNum) {
  481.         err = FSClose(infoPtr->fRefNum);
  482.         if (err!=noErr)
  483.             DoError(err);
  484.         infoPtr->fRefNum = 0;
  485.     }
  486.     if (infoPtr->resRefNum) {
  487.         DSIGCopySigsToTemp(infoPtr);
  488.         CloseResFile(infoPtr->resRefNum);
  489.         err = ResError();
  490.         if (err!=noErr)
  491.             DoError(err);
  492.         infoPtr->resRefNum = 0;
  493.     }
  494.  
  495.     infoPtr->saved = false;
  496.     infoPtr->changed = true;
  497.     
  498.     infoPtr->otherData[kLetterDescData] = nil;
  499.     
  500.     err = SMPNewMailer(window,topLeft,true,gPreferences.expandOnCreate,gIdentity,nil,0L);
  501.     if (err!=noErr)
  502.         DoError(err);
  503.     
  504.     err = SMPGetDimensions(&mWidth,&contHeight,&expHeight);
  505.     if (err!=noErr)
  506.         DoError(err);
  507.     if (infoPtr->otherFlags[kMailerExpanded])
  508.         infoPtr->topIndent = expHeight;
  509.     else
  510.         infoPtr->topIndent = contHeight;
  511.         
  512.     MoveScrollBars(window);
  513.  
  514.     EndWindowAccess(window,hState);
  515. }
  516.  
  517.  
  518. void MakeDrawingFromMailer(WindowPtr window)
  519. {
  520.     WInfoPtr infoPtr;
  521.     char hState;
  522.     
  523.     OSErr err;
  524.     
  525.     if (!CanCloseLetter(window))    // make sure no open enclosures
  526.         return;
  527.  
  528.     err = SMPDisposeMailer(window,&gPreferences.closeOptions);
  529.     if (err!=noErr)
  530.         DoError(err);
  531.     
  532.     SetWindowKind(window,kDrawWindow);
  533.  
  534.     infoPtr = BeginWindowAccess(window,&hState);
  535.  
  536.     infoPtr->topIndent = 0;
  537.     if (!CheckPageSize(window,infoPtr))        // draw area may have gotten too big for us
  538.         MoveScrollBars(window);
  539.     
  540.     if (infoPtr->fRefNum) {
  541.         err = FSClose(infoPtr->fRefNum);
  542.         if (err!=noErr)
  543.             DoError(err);
  544.         infoPtr->fRefNum = 0;
  545.     }
  546.     if (infoPtr->resRefNum) {
  547.         DSIGCopySigsToTemp(infoPtr);
  548.         CloseResFile(infoPtr->resRefNum);
  549.         err = ResError();
  550.         if (err!=noErr)
  551.             DoError(err);
  552.         infoPtr->resRefNum = 0;
  553.     }
  554.  
  555.     infoPtr->saved = false;
  556.     infoPtr->changed = true;
  557.  
  558.     if (infoPtr->otherData[kLetterDescData])
  559.         DisposHandleChk((Handle)infoPtr->otherData[kLetterDescData]);
  560.         
  561.     SetDrawMethods(infoPtr);
  562.  
  563.     EndWindowAccess(window,hState);
  564. }
  565.  
  566.  
  567. void FixMailerMenus(WindowPtr window,WInfoPtr infoPtr)
  568. {
  569.     #pragma unused (infoPtr)
  570.     MenuHandle theMenu;
  571.     Str255 removeMailerText;
  572.     OSErr err;
  573.     SMPMailerState state;
  574.     Boolean undoEnabled;
  575.     
  576.     // get mailer's state so we can set the menus
  577.     
  578.     err = SMPGetMailerState(window, &state);
  579.     if (err != noErr)
  580.         DoError(err);
  581.  
  582.     // edit menu
  583.     
  584.     theMenu = GetMHandle(kEditMenu);
  585.     EnableAllMenuItems(theMenu);
  586.     if (state.isTarget) {
  587.         if (!state.canCut)
  588.             DisableItem(theMenu, kCutItem);
  589.         if (!state.canCopy)
  590.             DisableItem(theMenu, kCopyItem);
  591.         if (!state.canPaste)
  592.             DisableItem(theMenu, kPasteItem);
  593.         if (!state.canClear)
  594.             DisableItem(theMenu, kClearItem);
  595.         if (!state.canSelectAll)
  596.             DisableItem(theMenu, kSelectAllItem);
  597.     }
  598.     else
  599.         FixDrawEditMenu();
  600.  
  601.     // fix undo item
  602.     
  603.     switch (state.undoState) {
  604.         case kSMPMailerUndo:
  605.             SetItem(theMenu,kUndoItem,state.undoWhat);
  606.             EnableItem(theMenu,kUndoItem);
  607.             ClearAppUndo();
  608.             undoEnabled = true;
  609.             break;
  610.         case kSMPUndoDisabled:
  611.             ClearAppUndo();
  612.             undoEnabled = SetupAppUndo();
  613.             break;
  614.         case kSMPAppMayUndo:
  615.             undoEnabled = SetupAppUndo();
  616.             break;
  617.     }
  618.  
  619.     if (state.isTarget && !state.canCut && !state.canCopy && !state.canPaste && !state.canClear &&
  620.         !state.canSelectAll && !undoEnabled)
  621.             DisableItem(theMenu,0);    // disable edit menu title
  622.  
  623.     // mail menu
  624.     
  625.     theMenu = GetMHandle(kMailMenu);
  626.     EnableAllMenuItems(theMenu);
  627.     GetResString(removeMailerText,kRemoveMailerTextID,kRemoveMailerText);
  628.     SetItem(theMenu,kAddRemMailItem,removeMailerText);
  629.     if (state.hasBeenReceived) {
  630.         DisableItem(theMenu, kSendItem);
  631.     }
  632.     else {
  633.         DisableItem(theMenu, kReplyItem);
  634.         DisableItem(theMenu, kReplyToAllItem);
  635.         DisableItem(theMenu, kForwardItem);
  636.         DisableItem(theMenu, kTagLetterItem);
  637.     }
  638.     
  639.     gMenusDirty = true;
  640. }
  641.  
  642.  
  643. pascal void DrawImageProc(long refCon, Boolean inColor)
  644. {
  645.     #pragma unused (inColor)
  646.     OpenCPicParams newHeader;
  647.     OSErr err;
  648.     Point zeroPt = {0,0};
  649.     WInfoPtr infoPtr;
  650.     TPrInfo prInfo;
  651.     
  652.     infoPtr = (WInfoPtr)refCon;
  653.     prInfo = (**(infoPtr->printRecord)).prInfo;
  654.     
  655.     newHeader.srcRect = prInfo.rPage;
  656.     newHeader.hRes = FixRatio(prInfo.iHRes,1);
  657.     newHeader.vRes = FixRatio(prInfo.iVRes,1);
  658.     newHeader.version = -2;
  659.     newHeader.reserved1 = 0;
  660.     newHeader.reserved2 = 0L;
  661.     
  662.     err = SMPNewPage(&newHeader);
  663.     if (err!=noErr)
  664.         DoError(err);
  665.         
  666.     DrawAllShapes(infoPtr,zeroPt);
  667. }
  668.  
  669.  
  670. pascal PicHandle DrawImageToPicture(WindowPtr window,WInfoPtr infoPtr)
  671. {
  672.     PicHandle thePicture;
  673.     RgnHandle saveRgn;
  674.     GrafPtr savePort;
  675.     Point zeroPt = {0,0};
  676.     TPrInfo prInfo;
  677.         
  678.     prInfo = (**(infoPtr->printRecord)).prInfo;
  679.  
  680.     GetPort(&savePort);
  681.     SetPort(window);
  682.     saveRgn = NewRgn();
  683.     GetClip(saveRgn);
  684.     ClipRect(&prInfo.rPage);
  685.     thePicture = OpenPicture(&prInfo.rPage);
  686.     DrawAllShapes(infoPtr,zeroPt);
  687.     ClosePicture();
  688.     SetClip(saveRgn);
  689.     DisposeRgn(saveRgn);
  690.     SetPort(savePort);
  691.     
  692.     return thePicture;
  693. }
  694.  
  695.  
  696. /*---------------------------------------------------------------------------*/
  697.  
  698. OSErr AddLetterBlocks(WindowPtr window,WInfoPtr infoPtr,SMPSendFormat *sendFormat)
  699. {
  700.     OSErr err = noErr;
  701.     
  702.     // add image
  703.     
  704.     if (!sendFormat || (sendFormat->whichFormats&kSMPImageMask)) {
  705.         err = AddLetterImage(window,infoPtr);
  706.         if (err!=noErr)
  707.             return err;
  708.     }
  709.     
  710.     // add standard letter interchange format
  711.     
  712.     if (!sendFormat || (sendFormat->whichFormats&kSMPStandardInterchangeMask)) {
  713.         err = AddStandardLetterContent(window,infoPtr);
  714.         if (err!=noErr)
  715.             return err;
  716.     }
  717.     
  718.     // add main (content) enclosure
  719.     
  720.     if (!sendFormat || (sendFormat->whichFormats&kSMPNativeMask)) {
  721.         err = AddContentEnclosure(window,infoPtr);
  722.         if (err!=noErr)
  723.             return err;
  724.     }
  725.     
  726.     return err;
  727. }
  728.  
  729.  
  730. OSErr AddContentEnclosure(WindowPtr window,WInfoPtr infoPtr)
  731. {
  732.     OSErr err;
  733.     FSSpec fSpec;
  734.  
  735.     err = SaveFileToTemp(infoPtr,&fSpec);
  736.     if (err!=noErr)
  737.         return err;
  738.     
  739.     err = SMPAddMainEnclosure(window,&fSpec);
  740.     
  741.     FSpDelete(&fSpec);
  742.     
  743.     return err;
  744. }
  745.  
  746.  
  747. OSErr AddStandardLetterContent(WindowPtr window,WInfoPtr infoPtr)
  748. {
  749.     OSErr err;
  750.     PicHandle thePicture;
  751.     
  752.     thePicture = DrawImageToPicture(window,infoPtr);
  753.     if (thePicture) {
  754.         HLock((Handle)thePicture);
  755.         err = SMPAddContent(window,kMailPictSegmentType,false,*thePicture,
  756.                 GetHandleSize((Handle)thePicture),nil,true,smRoman);
  757.         KillPicture(thePicture);
  758.     }
  759.     else return kInternalError;
  760.     
  761.     return err;
  762. }
  763.  
  764.  
  765. OSErr AddLetterImage(WindowPtr window,WInfoPtr infoPtr)
  766. {
  767.     return SMPImage(window,DrawImageProc,(long)infoPtr,false);
  768. }
  769.  
  770.  
  771. void HandleExpand(WindowPtr window,WInfoPtr infoPtr)
  772. {
  773.     OSErr err;
  774.     Rect rectToInval;
  775.     GrafPtr savePort;
  776.     short expHeight,contHeight,mWidth;
  777.     
  778.     err = SMPGetDimensions(&mWidth,&contHeight,&expHeight);
  779.     if (err!=noErr)
  780.         DoError(err);
  781.         
  782.     infoPtr->otherFlags[kMailerExpanded] = true;
  783.     infoPtr->topIndent = expHeight;
  784.     
  785.     rectToInval = window->portRect;
  786.     rectToInval.top += expHeight;
  787.     rectToInval.bottom -= kScrollBarWidth;
  788.     rectToInval.right -= kScrollBarWidth;
  789.     
  790.     GetPort(&savePort);
  791.     SetPort(window);
  792.     InvalRect(&rectToInval);
  793.     
  794.     MoveScrollBars(window);
  795.  
  796.     err = SMPExpandOrContract(window, true);
  797.     // ignore errors- we may already be expanded
  798.         
  799.     SetPort(savePort);
  800. }
  801.  
  802.  
  803. void HandleContract(WindowPtr window,WInfoPtr infoPtr)
  804. {
  805.     OSErr err;
  806.     Rect rectToInval;
  807.     GrafPtr savePort;
  808.     short expHeight,contHeight,mWidth;
  809.     
  810.     err = SMPGetDimensions(&mWidth,&contHeight,&expHeight);
  811.     if (err!=noErr)
  812.         DoError(err);
  813.  
  814.     infoPtr->otherFlags[kMailerExpanded] = false;
  815.     infoPtr->topIndent = contHeight;
  816.     
  817.     rectToInval = window->portRect;
  818.     rectToInval.top += contHeight;
  819.     rectToInval.bottom -= kScrollBarWidth;
  820.     rectToInval.right -= kScrollBarWidth;
  821.     
  822.     GetPort(&savePort);
  823.     SetPort(window);
  824.     InvalRect(&rectToInval);
  825.         
  826.     if (!CheckPageSize(window,infoPtr))        // draw area may have gotten too big for us
  827.         MoveScrollBars(window);
  828.     
  829.     // note that we don't call ExpandOrContract() to contract mailer- it's done by mail package
  830.     
  831.     SetPort(savePort);
  832. }
  833.  
  834.  
  835. Boolean CanCloseLetter(WindowPtr window)
  836. {
  837.     OSErr err;
  838.     WInfoPtr infoPtr;
  839.     char hState;
  840.     Boolean returnValue;
  841.     
  842.     returnValue = true;
  843.     infoPtr = BeginWindowAccess(window,&hState);
  844.  
  845.     if (IsWindowType(window,kDrawMailerWindow)) {
  846.     
  847.         //    display close options dialog
  848.         
  849.         if (gPreferences.closeOptionsDialog) {
  850.             SetCursor(&qd.arrow);
  851.             err = SMPCloseOptionsDialog(window,&gPreferences.closeOptions);
  852.             if (err!=noErr)
  853.                 returnValue = false;
  854.         }
  855.  
  856.         if (returnValue==true) {
  857.         
  858.             //  close main enclosure (if we're a received letter)
  859.  
  860.             if (infoPtr->fRefNum) {
  861.                 err = FSClose(infoPtr->fRefNum);
  862.                 if (err!=noErr)
  863.                     DoError(err);
  864.                 infoPtr->fRefNum = 0;
  865.             }
  866.             if (infoPtr->resRefNum) {
  867.                 CloseResFile(infoPtr->resRefNum);
  868.                 err = ResError();
  869.                 if (err!=noErr)
  870.                     DoError(err);
  871.                 infoPtr->resRefNum = 0;
  872.             }
  873.             
  874.             // see if we can close the letter now
  875.             
  876.             err = SMPPrepareToClose(window);
  877.             if (err==kSMPHasOpenAttachments) {
  878.                 SetCursor(&qd.arrow);
  879.                 StopAlert(kHasOpenAttachID,nil);
  880.                 returnValue = false;
  881.             }
  882.         }
  883.     }
  884.     
  885.     EndWindowAccess(window,hState);
  886.     return returnValue;
  887. }
  888.  
  889.  
  890. Boolean SameLetter(const LetterDescriptor *one,const LetterDescriptor *two)
  891. {
  892.     if (one->onDisk != two->onDisk)
  893.         return false;
  894.     
  895.     if (one->onDisk) {
  896.         
  897.         // compare fsspecs
  898.         
  899.         return ((one->u.fileSpec.vRefNum == two->u.fileSpec.vRefNum) &&
  900.             (one->u.fileSpec.parID == two->u.fileSpec.parID) &&
  901.             EqualString(one->u.fileSpec.name,two->u.fileSpec.name,false,true));
  902.     }
  903.     else {
  904.         
  905.         // compare letterspecs
  906.         
  907.         return ((one->u.mailboxSpec.spec[0] == two->u.mailboxSpec.spec[0]) &&
  908.                 (one->u.mailboxSpec.spec[1] == two->u.mailboxSpec.spec[1]) &&
  909.                 (one->u.mailboxSpec.spec[2] == two->u.mailboxSpec.spec[2]));
  910.     }
  911. }